//
// Created by 李传智 on 2018/4/12.
//

#include <android/native_window.h>
#include <EGL/egl.h>
#include "EGL.h"
#include "Logger.h"

class AndroidEGL : public EGL {

public:
    EGLDisplay display = EGL_NO_DISPLAY;
    EGLSurface surface = EGL_NO_SURFACE;
    EGLContext context = EGL_NO_CONTEXT;

    virtual bool init(void *_window) {
        ANativeWindow *window = (ANativeWindow *) _window;
        close();
        mutex.lock();
        // 初始化 egl
        // 1. 获取 eglDisplay 对象，显示设备
        display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        if (display == EGL_NO_DISPLAY) {
            LOG_E("eglGetDisplay failed");
            mutex.unlock();
            return false;
        }
        LOG_I("eglGetDisplay success");
        // 2. 初始化 display
        if (EGL_TRUE != eglInitialize(display, 0, 0)) {
            LOG_E("eglInitialize failed");
            mutex.unlock();
            return false;
        }
        LOG_I("eglInitialize success");
        // 3. 获取配置并创建surface
        EGLint configSpec[] = {
                EGL_RED_SIZE, 8,
                EGL_GREEN_SIZE, 8,
                EGL_BLUE_SIZE, 8,
                EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
                EGL_NONE
        };
        EGLConfig eglConfig = 0;
        EGLint numConfigs = 0;
        if (EGL_TRUE != eglChooseConfig(display, configSpec, &eglConfig, 1, &numConfigs)) {
            LOG_E("eglChooseConfig failed");
            mutex.unlock();
            return false;
        }
        surface = eglCreateWindowSurface(display, eglConfig, window, 0);
        // 4. 创建并切换 egl 上下文
        const EGLint contextSpec[] = {
                EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL_NONE
        };
        context = eglCreateContext(display, eglConfig, EGL_NO_CONTEXT, contextSpec);
        if (EGL_NO_CONTEXT == context) {
            LOG_E("eglCreateContext failed");
            mutex.unlock();
            return false;
        }
        if (EGL_TRUE != eglMakeCurrent(display, surface, surface, context)) {
            LOG_E("eglMakeCurrent failed");
            mutex.unlock();
            return false;
        }
        LOG_I("egl init success");
        mutex.unlock();
        return true;
    }

    virtual void close() {
        mutex.lock();
        if (display == EGL_NO_DISPLAY) {
            mutex.unlock();
            return;
        }
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_SURFACE);
        if (surface != EGL_NO_SURFACE) {
            eglDestroySurface(display, surface);
            surface = EGL_NO_SURFACE;
        }
        if (context != EGL_NO_CONTEXT) {
            eglDestroyContext(display, context);
            context = EGL_NO_CONTEXT;
        }
        eglTerminate(display);
        display = EGL_NO_DISPLAY;
        mutex.unlock();
    }

    virtual void draw() {
        mutex.lock();
        if (display == EGL_NO_DISPLAY || surface == EGL_NO_SURFACE) {
            mutex.unlock();
            return;
        }
        eglSwapBuffers(display, surface);
        mutex.unlock();
    }

protected:

    std::mutex mutex;
};

EGL *EGL::get() {
    static AndroidEGL egl;
    return &egl;
}